perm filename VDSK.FAI[CMS,LCS]1 blob
sn#362803 filedate 1978-06-22 generic text, type T, neo UTF8
00100 ;Floppy disk file system.
00200 .INSERT ASMBL.FAI[CMS,LCS]
00300
00400 ZERO ← 274 ;Fail offset
00500 LOC ZERO
00600
00700 CBLK: 0 ;Ram command block.
00800 CCNT: 0 ;C parameter count.
00900 CTRK: 0 ;C track
01000 CSEC: 0 ;C sector
01100 CLEN: 0 ;C length in sectors.
01200 BLOCK 3
01300 FCMD: 0 ;Disk command pointer.
01400 FCMDH: 0
01500 CMD: 0 ;File system command.
01502 CMDJMP: 0 ;Indirect command jump.
01503 CJMPH: 0 ;Msbyte.
01505 ERFLG: 0 ;Error flag/code.
01550 RFOPEN: 0 ;Read file open flag.
01600 WFOPEN: 0 ;Write file open flag
01700 FLEN: 0 ;File length. In sectors.
01800 SREM: 0 ;Sectors remaining. In sectors.
01900
02000 FBLK: 0 ;File block
02100 FNAM: BLOCK 11 ;9 Chr file name.
02200 FTRK: 0 ;Disk track number
02300 FSEC: 0 ;Disk sector number
02400 NSEC: 0 ;Number of sectors
02500 0
02600 0
02700 0
02800
02900 DBLK: 0 ;Directory block
03000 SCNT: 0 ;Number of sectors
03100 FCNT: 0 ;Number of files
03200 FFDIR: 0 ;First free directory block
03300 FFTRK: 0 ;First free data track
03400 FFSEC: 0 ;First free data sector
03500 FBLKS: 0 ;Number of free sectors. In sectors.
03600
03700 SPOINT: 0 ;SI/O pointer.
03800 SPOH: 0 ;Msbyte
03900 DPOINT: 0 ;Disk buffer bointer.
04000 DPOH: 0 ;Msbyte
04100
04200 LOC ZERO+1000
04300 FBUF: BLOCK 1000 ;Disk buffer
00100 LOC ZERO+17400 ;PROM Start address.
00200 CMDTBL:
00300 DINT ← 0
00400 65 ;Specify
00500 4 ;Parameter count.
00600 15 ;Init
00700 =20 ;Step rate in ms*2.
00800 =25 ;Head settling time in ms*2.
00900 252 ;H unload I cnt./ H load time.
01000 0
01100 0
01200 SBT ← 10
01300 65 ;Specify
01400 4
01500 20 ;Surface zero bad tracks command.
01600 377 ;No bad tracks.
01700 377
01800 0 ;Current track.
01900 0
02000 0
02100 DMA ← 20
02200 72 ;Write special register.
02300 2
02400 27 ;Mode register.
02500 2 ;DMA and single actuator.
02600 0
02700 0
02800 0
02900 0
03000 MON ← 30
03100 72 ;Write special register.
03200 2
03300 43 ;Drive control output register.
03400 40 ;Optional output / motor on bit.
03500 0
03600 0
03700 0
03800 0
03900 MOFF ← 40
04000 72 ;Write special register.
04100 2
04200 43 ;Drive control output register.
04300 0 ;Optional output / motor off.
04400 0
04500 0
04600 0
04700 0
04800 RHDR ← 50
04900 22 ;Read one sector command.
05000 2
05100 0 ;Header track number.
05200 0 ;Header sector number.
05300 0
05400 0
05500 0
05600 0
05700 WHDR ← 60
05800 12 ;Write one sector command.
05900 2
06000 0 ;Header track number.
06100 0 ;Header sector number.
06200 0
06300 0
06400 0
06500 0
06600 VHDR ← 70
06700 36 ;Verify one sector command.
06800 2
06900 0 ;Header track number.
07000 0 ;Header sector number.
07100 0
07200 0
07300 0
07400 0
00100 ;Power on reset.
00200 RST: LDXI 377 ;Setup stack.
00300 TXS
00400 CLD ;Clear decimal mode.
00500
00600 ;Reset I/O
00700 ;Init floppy disk controller.
00800 FDSKC ← FDSK ;Disk command/status register
00900 FDSKP ← FDSK+1 ;Disk parameter/result register
01000 FDSKR ← FDSK+2 ;Disk reset register.
01100
01200 LDAI 1 ;Reset disk again.
01300 STA FDSKR
01400 LSRA ;Clear A
01500 STA FDSKR
01600
01700 LDAI DINIT ;Disk initialization command.
01800 JSR PCMD ;Prom command.
01900 LDAI SBT ;Setup bad tracks
02000 JSR PCMD
02100 LDAI DMA ;Setup DMA mode.
02200 JSR PCMD
02300
02400 ;Reset SI/O
02500
02600 FOCLR: LDAI 0
02650 STAZ RFOPEN ;Reset read file open flag.
02700 STAZ WFOPEN ;Clear write file open flag.
02800 ;Reset command mode.
02900 DOFF: LDAI 0
03000 STAZ XFLG ;Set to command mode.
03100
03200 CLI ;Enable interrupts.
03300
03325 ;Add cli and sei for interrupt bind?
03350 CLRER: LDAI 0
03375 STAZ ERFLG ;Clear error flag.
03387
03400 IDLSET: LDAI 0 ;Reset idle mode.
03500 STAZ CMD
03600
03700 IDLE: BITZ ERFLG ;Check for error
03750 BMI DOERO
03775
03787 LDAZ CMD ;Check for input.
03800 BEQ IDLE
03900 ;Non-interrupt level command decode.
04000 BITZ NAMFLG ;Check if a file name.
04100 BPL DCODE
04150
04155 STAZX FNAME ;Save file name.
04160 INX ;X = name index.
04165 CPXI =9 ;# of chrs. in file name.
04170 BPL IDLESET ;Wait for the rest of name.
04175
04180 INX
04185 STXZ NAMFLG ;Reset name mode.
04190 RTS ;Return to command.
00100 DCODE: LDXI NCMDS ;# of commands.
00200 DL: CMPX CMDTBL ;Check if valid command.
00300 BEQ JCMD
00400 DEX
00500 BPL DL
00600 ;Illegal command.
00700 LDAI 4 ;Command error code.
00800 OACK: JSR OCHR ;Output status.
00900 JMP IDLSET
01000
01100 JCMD: LDAX JLTBL ;Get lsbyte of jump address.
01200 STAZ CMDJMP
01300 LDAX JHTBL ;Get msbyte.
01400 STAZ CJMPH
01450
01500 JMPIN CMDJMP ;Excute command.
01600
01700 NCMDS ← UNDEF ;# of commands.
01800 CMDTBL: "W" ;Write data
01900 "R" ;Read data
02000 "E" ;Enter write file.
02100 "C" ;Close write file.
02200 "O" ;Open read file.
02300 "K" ;Delete file.
02400 "D" ;Open directory.
02500 "N" ;Next directory block.
02600 "B" ;Free blp
02700 "F" ;Format disk.
02800 "I" ;Initialize directory.
02900 "Q" ;Compress holes.
03000
03100 CJMPL: WRT ;Lsbyte of command address.
03200 RD
03300 ENTR
03400 CLOZ
03500 OPIN
03600 KIL
03700 DIR
03800 NXTD
03900 BLKS
04000 FORM
04100 INITD
04200 CMPRES
04300
04400 CJMPH: ;Msbyte of command address.
00100 ;Write command to FDSKC
00200 RCMD: LDAI 0 ;Ram command.
00300 STAZ FCMD
00400 STAZ FCMDH
00500 BEQ WCMD
00600
00700 PCMD: STAZ FCMD ;Prom command.
00800 LDAI PROM ;Command table addr.
00900 STAZ FCMDH
01000
01100 WCMD: LDA FDSKC ;Wait until not busy.
01200 BMI WCMD
01300
01400 LDYI 0
01500 LDAIY FCMD ;Get command code.
01600 STA FDSKC ;Write in disk cotrol reg.
01700 INCZ FCMD ;Point to parameter count.
01800 LDAIY FCMD ;Get count.
01900 BEQ NOPAR ;If no parameters
02000 TAY
02100
02200 PARW: LDA FDSKC ;Read status
02300 ANDI 40 ;P reg full bit.
02400 BNE PARW ;Wait if still full.
02500
02600 LDAIY FCMD ;Parameter
02700 STA FDSKP
02800 DEY
02900 BNE PARW ;More left?
03000
03100 NOPAR: RTS
00100 ;IRQ maskable interrupt routines.
00200 IRQV: PHA ;Save registers
00300 TYA
00400 PHA
00500 TXA
00600 PHA
00700 ;Poll
00800 LDA FDSKC ;Read disk status.
00900 ANDI 10 ;IRQ bit
01000 BEQ SIO
01100
01200 ;Disk interrupt.
01300
01400 ;SI/O interrupt.
01500 SIO: LDYI 0 ;No index.
01600
01650 ;Check for SI/O error.
01700 ;Check if read or write.
01800
01900 ;Read SI/O
02000 RSIO: LDA SIOD ;Get byte from I/O
02100
02200 BITZ XFLG ;Check if command.
02300 BPL BUFIT
02400
02500 STAZ CMD ;Save command.
02600 JMP RTRN ;Return
02700
02800 ;SI/O to disk write buffer.
02900 BUFIT: BITZ BFFLG ;Check if write buffer full.
03000 BMI BFERR ;Error
03100
03200 STAIY SPOINT ;Save it.
03300 JMP INCSPO ;Increment SI/O buffer pointer.
00100 ;Output byte to SI/O.
00200 WSIO: BITZ BFFLG ;Check if buffer empty.
00300 BMI BFERR ;Buffer empty error.
00400
00500 LDAIY SPOINT ;Get byte from FBUF.
00600 STA SIOD ;Output it.
00700
00800 INCSPO: CLC
00850 ADCZ CKSUM ;Update check sum.
00875 STAZ CKSUM
00887 INCZ SPOINT
00900 BNE RTRN
01000
01100 LDAI 377
01200 STAZ BFFLG ;Set buffer done flag.
01300
01400 BITZ OBEMTY ;Check if other buffer done.
01500 BMI BFERR ;Buffer bind error.
01600
01700 LDAZ SPOH
01800 XORI 1 ;Swap buffers.
01900 STAZ SPOH
02000
02100 RTRN: PLA ;Restore registers
02200 TAX
02300 PLA
02400 TAY
02500 PLA
02600 RTI ;Return
00100 ;Non-maskable DRQ interrupt.
00200 NMIV: PHA ;Save registers
00300 TYA
00400 PHA
00500 LDYI 0 ;No index.
00600
00700 BITZ DIRC ;Get direction.
00800 BMI WDRQ ;Disk write.
00900
01000 LDA FDREG ;Read byte from disk.
01100
01200 STAIY DPOINT ;Save it in FBUF
01300 JMP INCPO ;Increment disk buffer pointer.
01400
01500 WDRQ: LDAIY DPOINT ;Get byte from FBUF.
01600 STA FDREG ;Write in disk data register.
01700
01800 INCPO: INCZ DPOINT
01900 BNE NRTRN ;Return if not done with buffer
02000
02100 LDAZ DPOH
02200 XORI 1 ;Swap buffers
02300 STAZ DPOH
02400
02500 NRTRN: PLA ;Restore registers.
02600 TAY
02700 PLA
02800 RTI ;Return
00100 ;Directory look up.
00200 LOKUP: LDAI 377
00300 STAZ NAMFLG ;Set get name.
00400 JSR IDLE ;Wait for it.
00500
00600 JSR RDTRK ;Read first directory track.
00700 LDAZ FBUF
00800 CMPI DMARK ;Check for header.
00900 BEQ BUMPIT
01000 ;No directory.
01050 BUMPIT: LDYI 20 ;Skip directory block.
01100 CKDIR: LDXI 0
01200 CKNAM: LDAY FBUF
01300 CMPZX FBLK ;Look for file name.
01400 BNE NXTF ;No match
01500 INY
01600 INX
01700 CPXI =10 ;9 chrs. + fmark
01800 BNE CKNAM
01900 ;Names match
02000 FMOV: LDAY FBUF ;Save file record.
02100 STAZX FBLK
02200 INY
02300 INX
02400 CPXI 20
02500 BNE FMOV
02600
02700 LDAI 0 ;Return with file found.
02800 RTS
02900
03000 NXTF: TYA ;Point to next file record.
03100 ORAI 17
03200 TAY
03300 INY
03400 BNE CKDIR
03500
03600 DECZ SREM ;Check if more sectors.
03700 BNE GETS
03750 FNF: LDAI 200 ;Return file not found code.
03775 RTS
03800
03900 GETS: INCZ CSEC ;Next sector
03950 ;No jsr?
04000 JSR RNDS ;Read next directory sector.
04100 LDYI 0
04200 BEQ CKDIR
00100 OPIN: JSR LOKUP ;Lookup file FNAM
00200 BEQ SETOPN
00250 RERR: ;Disk read error.
00275 JMP OACK ;Output error code.
00300
00400 SEEK: LDAZ FTRK ;Get track and sector
00500 STAZ CTRK
00600 LDAZ FSEC
00700 STAZ CSEC
00800 LDAI 377
00900 STAZ RFOPEN
01000 GACK: LDAI 6 ;<ack>
01100 JMP OACK
00100 SETBUF: LDAI FBUF ;Read disk into FBUF
00200 STAZ FLAD ;Setup buffer pointer.
00300 ASLA ;Clear A
00400 STAZ 31 ;FLAD+1
00500 LDXI 1 ;X=1 For one sector
00600 RTS
00700
00800 RBUF: JSR SETBUF ;Setup address
00900
01000 ;Read sectors from disk.
01100 READ: JSR FWAI ;Check if busy
01200 JSR SETTO ;Init timer
01300 LDAI 143 ;IBM read command (n secs)
01400 STA FDSKC
01500
01600 RSEC: LDYI 0
01700 FLOAD: LDA DSKSEL ;Check if byte ready
01800 BPL FLOAD
01900 LDA FDSKD ;Read byte from disk
02000 STAIY FLAD
02100 INY
02200 BPL FLOAD
02300
02400 LDAZ FLAD
02500 EORI 200 ;Next sector
02600 STAZ FLAD
02700 BMI NOPAGE
02800 INCZ FLAD+1
02900
03000 NOPAGE: DEX
03100 BNE RSEC ;More sectors
03200
03300 JSR ENDSK ;Reset disk, timer. Read status
03400 RTS
03500
03600 ENDSK: LDAI 57 ;End disk op
03700 STA FDSKC
03800 EOR FDSKC ;Read disk status
03900 ANDI 376 ;For busy bit
04000 RTS
00100 ;Create file routine
00200 ENTR: LDAZ FFTRK
00250 CMPI LASTRK ;Check if disk is full.
00275 BCC LOKIT
00287 ;Disk full
00293 LOKIT: JSR LOKUP ;Check if file already exists.
00300 BEQ FEXIST ;Check if file exists
00400 CMPI 200 ;Not in dir. code
00500 BEQ GFBLK
00550 ;Do disk error recovery.
00650 FEXIST: LDAI 2 ;File exists error code.
00750 JMP OACK
00800
00900 GFBLK: LDAZ FFTRK ;Get first free track.
01600 STAZ CTRK
01700 LDAZ FFSEC
01800 STAZ CSEC
02300 LDAI 377 ;Set write file open flag.
02400 STAZ WFOPEN
02600 JMP GACK ;Return with no errors
00100 WBUF: JSR SETBUF ;Write FBUF
00200
00300
00400 WRITE: JSR FWAI ;Check if busy.
00500 JSR SETTO ;Init timer
00600
00700 LDAI 103 ;Write multiple sectors command
00800 STA FDSKC
00900
01000 CLRY: LDYI 0
01100 WLOOP: LDA DSKSEL ;Wait until empty
01200 BPL WLOOP
01300
01400 LDAIY FLAD
01500 STA FDSKD ;Write chr on disk
01600 INY
01700 BPL WLOOP
01800
01900 QW: LDA DSKSEL ;Wait for 129th DRQ
02000 BPL QW
02100 STA FDSKD
02200
02300 LDAZ FLAD
02400 EORI 200 ;Next sector
02500 STAZ FLAD
02600 BMI CKMOR
02700 INCZ FLAD+1
02800 CKMOR: DEX ;More sectors
02900 BNE CLRY
03000
03100 JSR ENDSK ;Reset disk, timer. Read status
03200 BNE WERR ;Verify if no errors
00100 ;Verify disk write
00200 VERIFY: LDAZ FSEC ;Reset disk sector number
00300 STA FDSKS
00400 JSR SETTO ;Set timer
00500 LDXZ NSEC ;Get number of sectors
00600 LDAI 147 ;Read MS, HE.
00700 STA FDSKC
00800
00900 NXTS: LDYI 0
01000 VWAI: LDA DSKSEL ;Wait for byte
01100 BPL VWAI
01200 LDA FDSKD ;Read byte
01300 INY
01400 BPL VWAI ;Done with sector
01500
01600 DEX
01700 BNE NXTS ;Done with file
01800
01900 JSR ENDSK ;Reset disk, timer. Read status
02000 WERR: RTS ;Return with error bits
00100 CLOZE: BITZ WFOPEN ;Check if file open
00200 BMI UPDIR
00300 RERR: LDAI 377 ;Return with error
00400 RTS
00500
00600 ;Update directory
00700 UPDIR: LDAI 377 ;Get end of directory
00800 STAZ FTRK
00900 LDXZ SCNT ;Get sec.
01000 INX
01100 TXA
01200 EORI 377 ;Invert it
01300 STAZ FSEC
01400 STAZ OSEC
01500 JSR SEEK
01600 BNE RERR ;Seek error
01700 JSR RBUF ;Read end of directory.
01800 BNE RERR ;Read error
01900
02000 LDAZ FFTRK ;Point to new file
02100 STAZ FTRK
02200 LDAZ FFSEC
02300 STAZ FSEC
02400
02500 LDXZ FFDIR
02600
02700 ;BLT FBLK into directory
02800 LDYI 0
02900 NAMEIT: LDAY FBLK
03000 STAZX FBUF
03100 INX
03200 INY
03300 CPYI 20 ;FBLK Length
03400 BNE NAMEIT
03500
03600 LDXZ OSEC ;Point to end of directory
03700 STXZ FSEC
03800
03900 STX FDSKS
04000 LDXZ NSEC ;Save file length
04100 STXZ FLEN
04200 LDXI 1 ;For one sector
04300 STXZ NSEC
04400 JSR WBUF ;Write new file record
04500 BNE RERR ;Check for write error
04600
04700 INCZ FCNT
04800 CLC
04900 LDAZ FFDIR
05000 ADCI 20 ;Update end of dir.
05100 BPL SVSEC
05200 LDAI 0
05300 INCZ SCNT ;Next sector
05400
05500 SVSEC: STAZ FFDIR
05600
05700 LDAZ FFSEC
05800 SEC
05900 SBCZ FLEN ;Point to next free sector.
06000 STAZ FFSEC
06100
06200 LDAI 375
06300 STA FDSKS ;Start of directory
06400 JSR RBUF ;Read directory header
06500 BNE RERR ;Check for read error
06600
06700 LDXI 1
06800 STXZ NSEC
06900 LDXI 17 ;Header length
07000 HLOOP: LDAZX DBUF ;BLT Header into directory
07100 STAZX FBUF
07200 DEX
07300 BPL HLOOP
07400
07500 JSR WBUF ;Write directory
07600 BNE RERR ;Write error
07700 STAZ WFOPEN ;Reset write file open flag
07800
07900 RTS
00100 END